function Tree = climbtree()
% climbtree  Create tree structure based on Contents files.

STRUCT_TEMPLATE = struct( ...
    'FILENAME', cell(1,0), ...
    'SYNTAX', cell(1,0), ...
    'REF', cell(1,0), ...
    'DESCRIPT', cell(1,0), ...
    'HELPTEXT', cell(1,0), ...
    'Contents', cell(1,0) ...
    );

%--------------------------------------------------------------------------

[~,inDescript,inFile,inHelpText] = xxHeadline('Contents/index');

[chFileName,ch,chDescript,chHelpText] = xxPopulateFile(inFile);
nChapter = length(chFileName);

Tree = STRUCT_TEMPLATE;
Tree(1).SYNTAX = 'index';
Tree(1).FILENAME = inFile;
Tree(1).REF = 'Contents/index';
Tree(1).DESCRIPT = inDescript;
Tree(1).HELPTEXT = inHelpText;
Tree(1).Contents = STRUCT_TEMPLATE;

for i = 1 : nChapter

    [topicFileName, topic, topicDescript, topicHelpText] ...
        = xxPopulateFile(chFileName{i});
    nTopic = length(topicFileName);
    
    x = STRUCT_TEMPLATE;
    x(1).SYNTAX = ch{i};
    x(1).FILENAME = chFileName{i};
    x(1).REF = [ 'Contents/', x.SYNTAX ];
    x(1).DESCRIPT = chDescript{i};
    x(1).HELPTEXT = chHelpText{i};
    x(1).Contents = STRUCT_TEMPLATE;
    Tree.Contents(i) = x;

    for j = 1 : nTopic
        [funcFileName, func, funcDescript, funcHelpText] = ...
            xxPopulateFile(topicFileName{j});
        nFile = length(funcFileName);
        
        x = STRUCT_TEMPLATE;
        x(1).SYNTAX = topic{j};
        x(1).FILENAME = topicFileName{j};
        x(1).REF = [ x.SYNTAX, '/Contents' ];
        x(1).DESCRIPT = topicDescript{j};
        x(1).HELPTEXT = topicHelpText{j};
        x(1).Contents = STRUCT_TEMPLATE;
        Tree.Contents(i).Contents(j) = x;
        
        for k = 1 : nFile
            x = STRUCT_TEMPLATE;
            x(1).SYNTAX = func{k};
            x(1).FILENAME = funcFileName{k};
            if ~isempty(funcFileName{k}) && ~isequaln(funcFileName{k},NaN)
                [~, ref2] = fileparts(funcFileName{k});
            else
                ref2 = func{k};
            end
            x(1).REF = [ topic{j}, '/', ref2 ];
            x(1).DESCRIPT = funcDescript{k};
            x(1).HELPTEXT = funcHelpText{k};
            Tree.Contents(i).Contents(j).Contents(k) = x;
        end
    end
end

end


% Subfunctions...


%**************************************************************************


function [List,Syntax,Descript,HelpText,C] = xxPopulateFile(File,IsSave)
    try
        IsSave; %#ok<VUNUS>
    catch %#ok<CTCH>
        IsSave = true;
    end
    fprintf('Populating TOC in %s...',File);
    C = file2char(File);
    C = textfun.converteols(C);
    [C,List,Syntax,Descript,HelpText] = xxExpandLinks(C,File);
    if IsSave
        fprintf(' Saving...');
        char2file(C,File);
        rehash;
    end
    fprintf('\n');
end % xxPopulateFile()


%**************************************************************************


function [C,List,Syntax,Descript,HelpText] = xxExpandLinks(C,File) %#ok<*INUSD>
    List = {};
    Syntax = {};
    Descript = {};
    HelpText = {};
    invalid = {};
    replaceFunc = @doReplace; %#ok<NASGU>
    C = regexprep(C,'^(\s*% \* )\[([^\n]*?)\]\(([^\)\n]+)\)([ -]?)[^\n]*', ...
        '${replaceFunc($1,$2,$3,$4)}','lineanchors');
    if ~isempty(invalid)
        fprintf('\n');
        utils.error('irisroom:climbtree', ...
            'Invalid reference: %s.', ...
            invalid{:});
    end
        
    function C = doReplace(C1,C2,C3,C4)
        % fprintf('%s %s %s\n',C1,C2,C3);
        [syntax,descript,file,helpText] = xxHeadline(C3);
        if isequaln(Syntax,NaN),
            invalid{end+1} = C3;
            C = '';
            return
        end
        if ~isempty(C4)
            C = [C1,'[',C2,'](',C3,') - ',descript,'.'];
        else
            C = [C1,'[',descript,'](',C3,')'];
        end
        List{end+1} = file;
        Syntax{end+1} = syntax;
        Descript{end+1} = descript;
        HelpText{end+1} = helpText;
    end

end % xxExpandLinks()


%**************************************************************************


function [Syntax,Descript,File,H] = xxHeadline(Ref)
H = help(Ref);
File = xxRef2File(Ref);
if isempty(H)
    H = help(File);
end

if isempty(H)
    Syntax = NaN;
    Descript = NaN;
    return
end

% Remove 'Help for XXXX/XXX is inherited from superclass...')
H = regexprep(H,'^[ ]*Help for \w+/\w+ is inherited [^\n]*\n', ...
    '','lineanchors');

% Read H1 line.
tok = regexp(H,'^  ([^ ]+)  ([^\n]+)','tokens','once');
if isempty(tok) || isempty(tok{1}) || isempty(tok{2})
    utils.error('iris:help', ...
        'Invalid H1 line in %s.',Ref);
end

Syntax = strtrim(tok{1});
Descript = strtrim(tok{2});
if ~isempty(Descript) && Descript(end) == '.'
    Descript(end) = '';
end
end


%**************************************************************************


function File = xxRef2File(Ref)
trimfunc = @(x) strtrim(regexprep(x,'%.*',''));
% Existing folder/file reference.
File = which(Ref);
if ~isempty(File)
    File = trimfunc(File);
    return
end

[folder,title] = fileparts(Ref);
if strcmpi(folder,'contents')
    folder = 'Contents';
end

% Existing folder.file reference.
File = which([folder,'.',title]);
if ~isempty(File)
    File = trimfunc(File);
    return
end

% Chapter master file.
File = which(['+',folder,'/',title]);
if ~isempty(File)
    File = trimfunc(File);
    return
end

if ~isempty(strfind(Ref,'config')) && isempty(strfind(Ref,'Contents'))
    File = which(title);
    return
end

% Class constructor.
if ~strcmpi(folder,'contents') && strcmpi(title,'contents')
    File = which(folder);
    if ~isempty(File)
        File = trimfunc(File);
        return
    end
end
end % xxRef2File()
